#include "header.h"

char CompressionServerIP[MAX_IPV4_IP_LEN];

int main(int argc, char *argv[])
{
	FILE *fp;
	int ret, pid;
	int sockfd, connfd;
	char *buf, sendfile[MAX_FILENAME_LEN];
	struct sockaddr_in SockAddr;
	struct credential *credential;
	struct stat stat;
	unsigned int len = sizeof(SockAddr);

	/* Validate command line arguments */
	if (validateinfo(argc, argv) < 0) {
		printf("usage Server <Port no>\n");
		goto end;
	}

	pid = fork();
	if (0 != pid) {
		Multicast();
	} else {
		//Get compression server IP address
		ret = getCompressionServer();
		if (FAILURE == ret || NULL == CompressionServerIP) {
			printf("Unable to get compression server IP address\n");
			goto end;
		}

		printf("Decryption server IP resolved successfully: %s\n", CompressionServerIP);

		/* Create socket for control connection */
		sockfd = socket(AF_INET, SOCK_STREAM, 0);
		if (FAILURE == sockfd) {
			printf("Unable to create socket for control channel\n");
			goto end;
		}

		memset(&SockAddr, 0, sizeof(SockAddr));
		SockAddr.sin_family = AF_INET;
		SockAddr.sin_port = htons(atoi(argv[1]));
		SockAddr.sin_addr.s_addr = INADDR_ANY;

		/* Bind socket */
		ret = bind(sockfd, (struct sockaddr *)&SockAddr, sizeof(SockAddr));
		if (FAILURE == ret) {
			printf("Unable to bind with specified port no\n");
			close(sockfd);
			goto end;
		}

		/* Change server to passive mode and specify backlog : max no of connection request in waitnig queue */
		ret = listen(sockfd, MAX_TCP_BACKLOG);
		if (FAILURE == ret) {
			printf("Unable to listen on specified socket\n");
			close(sockfd);
			goto end;
		}

		while (1) {
			/* Accept incomming TCP connection */
			connfd = accept(sockfd, (struct sockaddr *)&SockAddr, &len);
			if (FAILURE == ret) {
				printf("unable to accept TCP connection\n");
				close(sockfd);
				goto end;
			}

			pid = fork();

			if (0 != pid) {
				close(connfd);
			}
			else {
				buf = (char *) malloc(CONTROL_INFO_RECV_LEN);

				/* Receive control information from the client */
				ret = recv(connfd, buf, CONTROL_INFO_RECV_LEN, 0);
				if (FAILURE == ret) {
					printf("unable to recv control data from client\n");
					free(buf);
					goto endChild;
				}

				printf("Control info has been received\n");
				credential = (struct credential *) buf;

				ret = chdir("./temp");
				if (FAILURE == ret) {
					printf("Unable to change directory\n");
					free(buf);
					goto endChild;
				}

				/* Create file */
				fp = fopen(credential->filename, "wb+");
				if (NULL == fp) {
					printf("Unable to create file : %s\n", credential->filename);
					free(buf);
					goto endChild;
				}

				/* Set the file size */
				ret = truncate(credential->filename, credential->size);
				if (FAILURE == ret) {
					printf("Unable to truncate file\n");
					free(buf);
					fclose(fp);
					goto endChild;
				}

				recvfile(connfd, fp, credential->size);
				fclose(fp);

				printf("File %s received for decompression\n", credential->filename);

				strcpy(sendfile, credential->filename);
				sendfile[strlen(credential->filename)-4] = '\0';
				strcat(sendfile, ".b64");

				ret = encrypt(credential->filename);
				if (FAILURE == ret) {
					printf("Unable to decompress file\n");
					goto endChild;
				}

				printf("File %s has been decompressed\n", credential->filename);

				ret = lstat(sendfile, (struct stat *) &stat);
				if (FAILURE == ret) {
					printf("Unable to get filesize\n");
					free(buf);
					goto endChild;
				}

				//Contact Compression server
				sendControlInfoAndFile(SockAddr.sin_addr.s_addr, sendfile, sendfile, stat.st_size);

				printf("File %s has been sent to decryption server\n", sendfile);

				ret = remove(credential->filename);
				if (FAILURE == ret) {
					printf("Unable to delete temporary file : %s\n", credential->filename);
				}

				ret = remove(sendfile);
				if (FAILURE == ret) {
					printf("Unable to delete temporary files : %s\n", sendfile);
				}

				ret = chdir("../");
				if (FAILURE == ret) {
					printf("Unable to change directory\n");
					free(buf);
					goto endChild;
				}

				free(buf);
endChild:
				close(connfd);
			}
		}
	}

end:
	return 0;
}

